/**************************************************************************//**
 * @file    Haversine.c
 * @author  İsmail SEZEN (email: sezenismail@gmail.com)
 * @date    02-08-2009
 *
 * @see http://mathforum.org/library/drmath/view/51879.html
 * @see http://www.faqs.org/faqs/geography/infosystems-faq/
 * @see http://blog.julien.cayzac.name/2008/10/arc-and-distance-between-two-points-on.html
 *
 * <b>Description</b>
 *
 * Haversine distance calculation module. This module helps to calculate
 * the distance between two global coordinate locations.\n
 *
 * Copyright (C) 2009 İsmail SEZEN
 *
 * <b>License</b>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *****************************************************************************/

/*Include Directives*///{
#define _GNU_SOURCE
#include <math.h>
//}

/*Variables *///{
/*! \brief Earth Radius in Kilometers - this constant is used in \ref Haversine_Distance formula. */
static const double R = 6372.797560856;
/*Degree vs. Radian conservation variables*/
/*! \brief Degree to Radian Conversation Constant */
static const double DEG_TO_RAD = M_PI/180.0;
/*! \brief Radian to Degree Conversation Constant */
static const double RAD_TO_DEG = 180.0/M_PI;
//}

/*! @brief Calculates the distance between two locations specified by latitute and longtitude.
 *  @param[in] lat1 is latitude of first location.
 *  @param[in] lon1 is the longtitude of first location.
 *  @param[in] lat2 is the latitude of latter location.
 *  @param[in] lon2 is the longtitude of latter location.
 *  @return Distance between specified two locations. */
double Haversine_Distance(double lat1,double lon1, double lat2, double lon2){
	double dlon = (lon2 - lon1) * DEG_TO_RAD;
	double dlat = (lat2 - lat1) * DEG_TO_RAD;
	double a =  pow(sin(dlat * 0.5),2)+ cos(lat1*DEG_TO_RAD) * cos(lat2*DEG_TO_RAD) * pow(sin(dlon * 0.5),2);
	double c = 2.0 * atan2(sqrt(a), sqrt(1-a));
	return R * c;
}

/*! @brief Calculates the difference between two longtitude by latitude and distance.
 *  @param[in] lat1 is latitude of first location.
 *  @param[in] lat2 is the latitude of latter location.
 *  @param[in] d is the distance between specified latitudes.
 *  @return londelta = lon2 - lon1 */
double Haversine_Longtitude_Delta(double lat1,double lat2, double d){
//          dlon = lon2 - lon1
//          dlat = lat2 - lat1
//          a = sin^2(dlat/2) + cos(lat1) * cos(lat2) * sin^2(dlon/2)
//          c = 2 * arcsin(min(1,sqrt(a)))
//          d = R * c
double lat1rad = lat1 * DEG_TO_RAD;
double lat2rad = lat2 * DEG_TO_RAD;
double dlatrad = lat2rad - lat1rad;
double c = d/R;
double tan_pow_2 = pow(tan(c/2),2);
double a = (tan_pow_2) / (1 - tan_pow_2);
double dlonrad = 2 * asin( sqrt( (a - pow(sin(dlatrad/2),2)) / (cos(lat1rad) * cos(lat2rad)) ) );
return dlonrad * RAD_TO_DEG;
}
